From 2ccb7f618db06b1fc8082c30ec5ad928d51309c9 Mon Sep 17 00:00:00 2001 From: Yunwen Zheng Date: Wed, 5 Nov 2025 08:59:07 -0500 Subject: [PATCH] ConfigFormGithubCollapse: Hide github features section if nothing is available (#113410) ConfigFormGithubCollapse: Hide github features section if nothing is available. Added unit tests --- eslint-suppressions.json | 5 - .../Config/ConfigFormGithubCollapse.test.tsx | 110 ++++++++++++++++++ .../Config/ConfigFormGithubCollapse.tsx | 96 ++++++++------- 3 files changed, 163 insertions(+), 48 deletions(-) create mode 100644 public/app/features/provisioning/Config/ConfigFormGithubCollapse.test.tsx diff --git a/eslint-suppressions.json b/eslint-suppressions.json index a3292e1a102..6392492ae77 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -3313,11 +3313,6 @@ "count": 3 } }, - "public/app/features/provisioning/Config/ConfigFormGithubCollapse.tsx": { - "no-restricted-syntax": { - "count": 2 - } - }, "public/app/features/provisioning/Shared/BranchValidationError.tsx": { "react/no-unescaped-entities": { "count": 26 diff --git a/public/app/features/provisioning/Config/ConfigFormGithubCollapse.test.tsx b/public/app/features/provisioning/Config/ConfigFormGithubCollapse.test.tsx new file mode 100644 index 00000000000..a3679340204 --- /dev/null +++ b/public/app/features/provisioning/Config/ConfigFormGithubCollapse.test.tsx @@ -0,0 +1,110 @@ +import { render, screen } from '@testing-library/react'; +import { UseFormRegister } from 'react-hook-form'; +import { MemoryRouter } from 'react-router-dom-v5-compat'; + +import { useGetFrontendSettingsQuery } from 'app/api/clients/provisioning/v0alpha1'; + +import { checkImageRenderer, checkImageRenderingAllowed, checkPublicAccess } from '../GettingStarted/features'; +import { RepositoryFormData } from '../types'; + +import { ConfigFormGithubCollapse } from './ConfigFormGithubCollapse'; + +jest.mock('app/api/clients/provisioning/v0alpha1', () => ({ + useGetFrontendSettingsQuery: jest.fn(), +})); + +jest.mock('../GettingStarted/features', () => ({ + checkImageRenderer: jest.fn(), + checkPublicAccess: jest.fn(), + checkImageRenderingAllowed: jest.fn(), +})); + +const mockUseGetFrontendSettingsQuery = useGetFrontendSettingsQuery as jest.MockedFunction< + typeof useGetFrontendSettingsQuery +>; +const mockCheckImageRenderer = checkImageRenderer as jest.MockedFunction; +const mockCheckPublicAccess = checkPublicAccess as jest.MockedFunction; +const mockCheckImageRenderingAllowed = checkImageRenderingAllowed as jest.MockedFunction< + typeof checkImageRenderingAllowed +>; + +type SetupOptions = { + isPublic?: boolean; + hasImageRenderer?: boolean; + imageRenderingAllowed?: boolean; + settingsData?: unknown; +}; + +function setup(options: SetupOptions = {}) { + const { isPublic = true, hasImageRenderer = true, imageRenderingAllowed = true, settingsData } = options; + + const data = settingsData ?? { allowImageRendering: imageRenderingAllowed }; + + mockCheckPublicAccess.mockReturnValue(isPublic); + mockCheckImageRenderer.mockReturnValue(hasImageRenderer); + mockCheckImageRenderingAllowed.mockReturnValue(imageRenderingAllowed); + mockUseGetFrontendSettingsQuery.mockReturnValue({ data } as never); + + const registerMock = jest.fn().mockReturnValue({}); + + const renderResult = render( + + } /> + + ); + + return { renderResult, registerMock }; +} + +describe('ConfigFormGithubCollapse', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns null when image rendering is not allowed on a public instance', () => { + const { renderResult } = setup({ imageRenderingAllowed: false, isPublic: true }); + + expect(renderResult.container).toBeEmptyDOMElement(); + expect(screen.queryByText('GitHub features')).not.toBeInTheDocument(); + }); + + it('renders preview checkbox when image rendering is allowed', () => { + const { registerMock } = setup({ imageRenderingAllowed: true, isPublic: true, hasImageRenderer: true }); + + expect(screen.getByText('GitHub features')).toBeInTheDocument(); + const checkbox = screen.getByRole('checkbox', { + name: /Enable dashboard previews in pull requests/i, + }); + expect(checkbox).toBeEnabled(); + expect(registerMock).toHaveBeenCalledWith('generateDashboardPreviews'); + }); + + it('disables preview checkbox when image renderer is unavailable', () => { + setup({ hasImageRenderer: false }); + + const checkbox = screen.getByRole('checkbox', { + name: /Enable dashboard previews in pull requests/i, + }); + expect(checkbox).toBeDisabled(); + }); + + it('disables preview checkbox and shows realtime feedback info on private instances', () => { + setup({ isPublic: false, imageRenderingAllowed: true }); + + const checkbox = screen.getByRole('checkbox', { + name: /Enable dashboard previews in pull requests/i, + }); + expect(checkbox).toBeDisabled(); + expect(screen.getByRole('link', { name: 'Configure webhooks' })).toBeInTheDocument(); + }); + + it('hides preview checkbox when image rendering is not allowed', () => { + setup({ imageRenderingAllowed: false, isPublic: false }); + + expect( + screen.queryByRole('checkbox', { + name: /Enable dashboard previews in pull requests/i, + }) + ).not.toBeInTheDocument(); + }); +}); diff --git a/public/app/features/provisioning/Config/ConfigFormGithubCollapse.tsx b/public/app/features/provisioning/Config/ConfigFormGithubCollapse.tsx index 3c397fefea0..1d77c9ad89b 100644 --- a/public/app/features/provisioning/Config/ConfigFormGithubCollapse.tsx +++ b/public/app/features/provisioning/Config/ConfigFormGithubCollapse.tsx @@ -1,7 +1,7 @@ import { UseFormRegister } from 'react-hook-form'; import { Trans, t } from '@grafana/i18n'; -import { Checkbox, ControlledCollapse, Field, Text, TextLink } from '@grafana/ui'; +import { Checkbox, ControlledCollapse, Field, Stack, Text, TextLink } from '@grafana/ui'; import { useGetFrontendSettingsQuery } from 'app/api/clients/provisioning/v0alpha1'; import { checkImageRenderer, checkPublicAccess, checkImageRenderingAllowed } from '../GettingStarted/features'; @@ -18,54 +18,64 @@ export function ConfigFormGithubCollapse({ register }: ConfigFormGithubCollapseP const hasImageRenderer = checkImageRenderer(); const imageRenderingAllowed = checkImageRenderingAllowed(settings.data); + if (!imageRenderingAllowed && isPublic) { + // don't display the whole collapse if neither feature is applicable + return null; + } + return ( - {imageRenderingAllowed && ( - - - - Adds an image preview of dashboard changes in pull requests. Images of your Grafana dashboards will be - shared in your Git repository and visible to anyone with repository access. - {' '} - - - Requires image rendering.{' '} - - Set up image rendering - - - - - } - {...register('generateDashboardPreviews')} - /> - - )} + + {imageRenderingAllowed && ( + + + + Adds an image preview of dashboard changes in pull requests. Images of your Grafana dashboards will + be shared in your Git repository and visible to anyone with repository access. + {' '} + + + Requires image rendering.{' '} + + Set up image rendering + + + + + } + {...register('generateDashboardPreviews')} + /> + + )} - {!isPublic && ( - - - - - Configure webhooks - {' '} - to get instant updates in Grafana as soon as changes are committed. Review and approve changes using pull - requests before they go live. - - - - )} + {!isPublic && ( + + + + + Configure webhooks + {' '} + to get instant updates in Grafana as soon as changes are committed. Review and approve changes using + pull requests before they go live. + + + + )} + ); }