Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
ConfigFormGithubCollapse: Hide github features section if nothing is …
…available. Added unit tests
  • Loading branch information
ywzheng1 committed Nov 4, 2025
commit 7af379779b0b21b771ba4ee2301e4e1866f5a0dd
5 changes: 0 additions & 5 deletions eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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<typeof checkImageRenderer>;
const mockCheckPublicAccess = checkPublicAccess as jest.MockedFunction<typeof checkPublicAccess>;
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(
<MemoryRouter>
<ConfigFormGithubCollapse register={registerMock as unknown as UseFormRegister<RepositoryFormData>} />
</MemoryRouter>
);

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();
});
});
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 (
<ControlledCollapse
label={t('provisioning.config-form-github-collapse.label-git-hub-features', 'GitHub features')}
isOpen={true}
>
{imageRenderingAllowed && (
<Field>
<Checkbox
disabled={!hasImageRenderer || !isPublic}
label={t('provisioning.finish-step.label-enable-previews', 'Enable dashboard previews in pull requests')}
description={
<>
<Trans i18nKey="provisioning.finish-step.description-enable-previews">
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.
</Trans>{' '}
<Text italic>
<Trans i18nKey="provisioning.finish-step.description-image-rendering">
Requires image rendering.{' '}
<TextLink
variant="bodySmall"
external
href="https://grafana.com/grafana/plugins/grafana-image-renderer"
>
Set up image rendering
</TextLink>
</Trans>
</Text>
</>
}
{...register('generateDashboardPreviews')}
/>
</Field>
)}
<Stack direction="column" gap={2}>
{imageRenderingAllowed && (
Copy link
Member Author

@ywzheng1 ywzheng1 Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no logic changes from here to the end, things changes:

  • code moved inside Stack component
  • added noMargin props to Field

<Field noMargin>
<Checkbox
disabled={!hasImageRenderer || !isPublic}
label={t('provisioning.finish-step.label-enable-previews', 'Enable dashboard previews in pull requests')}
description={
<>
<Trans i18nKey="provisioning.finish-step.description-enable-previews">
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.
</Trans>{' '}
<Text italic>
<Trans i18nKey="provisioning.finish-step.description-image-rendering">
Requires image rendering.{' '}
<TextLink
variant="bodySmall"
external
href="https://grafana.com/grafana/plugins/grafana-image-renderer"
>
Set up image rendering
</TextLink>
</Trans>
</Text>
</>
}
{...register('generateDashboardPreviews')}
/>
</Field>
)}

{!isPublic && (
<Field label={t('provisioning.config-form-github-collapse.label-realtime-feedback', 'Realtime feedback')}>
<Text variant="bodySmall" color={'secondary'}>
<Trans i18nKey={'provisioning.config-form-github-collapse.description-realtime-feedback'}>
<TextLink variant={'bodySmall'} href={GETTING_STARTED_URL}>
Configure webhooks
</TextLink>{' '}
to get instant updates in Grafana as soon as changes are committed. Review and approve changes using pull
requests before they go live.
</Trans>
</Text>
</Field>
)}
{!isPublic && (
<Field
noMargin
label={t('provisioning.config-form-github-collapse.label-realtime-feedback', 'Realtime feedback')}
>
<Text variant="bodySmall" color={'secondary'}>
<Trans i18nKey={'provisioning.config-form-github-collapse.description-realtime-feedback'}>
<TextLink variant={'bodySmall'} href={GETTING_STARTED_URL}>
Configure webhooks
</TextLink>{' '}
to get instant updates in Grafana as soon as changes are committed. Review and approve changes using
pull requests before they go live.
</Trans>
</Text>
</Field>
)}
</Stack>
</ControlledCollapse>
);
}
Loading