DashboardLibrary: Add template dashboard tests (#114179)
* dashboard template tests * command plaette restored * command plaette restored
This commit is contained in:
@@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event';
|
||||
import { TestProvider } from 'test/helpers/TestProvider';
|
||||
|
||||
import { NavModelItem } from '@grafana/data';
|
||||
import { reportInteraction } from '@grafana/runtime';
|
||||
import { config, reportInteraction } from '@grafana/runtime';
|
||||
|
||||
import { QuickAdd } from './QuickAdd';
|
||||
|
||||
@@ -11,6 +11,13 @@ jest.mock('@grafana/runtime', () => {
|
||||
return {
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
reportInteraction: jest.fn(),
|
||||
getDataSourceSrv: () => ({
|
||||
getList: jest
|
||||
.fn()
|
||||
.mockReturnValue([
|
||||
{ name: 'Test Data Source', uid: 'test-data-source-uid', type: 'grafana-testdata-datasource' },
|
||||
]),
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -74,4 +81,31 @@ describe('QuickAdd', () => {
|
||||
from: 'quickadd',
|
||||
});
|
||||
});
|
||||
|
||||
describe('Dashboard from template button', () => {
|
||||
beforeEach(() => {
|
||||
config.featureToggles.dashboardTemplates = true;
|
||||
});
|
||||
|
||||
it('shows a `Dashboard from template` button when the feature flag is enabled', async () => {
|
||||
setup();
|
||||
await userEvent.click(screen.getByRole('button', { name: 'New' }));
|
||||
expect(screen.getByRole('link', { name: 'Dashboard from template' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show a `Dashboard from template` button when the feature flag is disabled', async () => {
|
||||
config.featureToggles.dashboardTemplates = false;
|
||||
setup();
|
||||
await userEvent.click(screen.getByRole('button', { name: 'New' }));
|
||||
expect(screen.queryByRole('link', { name: 'Dashboard from template' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('redirects the user to the dashboard from template page when the button is clicked', async () => {
|
||||
setup();
|
||||
|
||||
await userEvent.click(screen.getByRole('button', { name: 'New' }));
|
||||
const link = screen.getByRole('link', { name: 'Dashboard from template' });
|
||||
expect(link).toHaveAttribute('href', '/dashboards?templateDashboards=true&source=quickAdd');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { ComponentProps } from 'react';
|
||||
import { useParams } from 'react-router-dom-v5-compat';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
@@ -5,7 +6,7 @@ import { render as testRender, screen, waitFor } from 'test/test-utils';
|
||||
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { config, setBackendSrv } from '@grafana/runtime';
|
||||
import { setupMockServer } from '@grafana/test-utils/server';
|
||||
import server, { setupMockServer } from '@grafana/test-utils/server';
|
||||
import { getFolderFixtures } from '@grafana/test-utils/unstable';
|
||||
import { backendSrv } from 'app/core/services/backend_srv';
|
||||
import { contextSrv } from 'app/core/services/context_srv';
|
||||
@@ -41,9 +42,25 @@ jest.mock('react-router-dom-v5-compat', () => ({
|
||||
useParams: jest.fn().mockReturnValue({}),
|
||||
}));
|
||||
|
||||
function render(ui: Parameters<typeof testRender>[0]) {
|
||||
jest.mock('@grafana/runtime', () => {
|
||||
return {
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
getDataSourceSrv: () => ({
|
||||
getList: jest
|
||||
.fn()
|
||||
.mockReturnValue([
|
||||
{ name: 'Test Data Source', uid: 'test-data-source-uid', type: 'grafana-testdata-datasource' },
|
||||
]),
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
function render(ui: Parameters<typeof testRender>[0], options: Parameters<typeof testRender>[1] = {}) {
|
||||
return testRender(ui, {
|
||||
preloadedState: { navIndex: { 'dashboards/browse': { text: 'Dashboards', id: 'dashboards/browse' } } },
|
||||
preloadedState: {
|
||||
navIndex: { 'dashboards/browse': { text: 'Dashboards', id: 'dashboards/browse' } },
|
||||
},
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -324,4 +341,42 @@ describe('browse-dashboards BrowseDashboardsPage', () => {
|
||||
expect(checkbox).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Template dashboard modal', () => {
|
||||
beforeEach(() => {
|
||||
config.featureToggles.dashboardTemplates = true;
|
||||
server.use(
|
||||
http.get('/api/gnet/dashboards', () => {
|
||||
return HttpResponse.json({
|
||||
page: 1,
|
||||
pages: 1,
|
||||
items: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Test Template Dashboard',
|
||||
description: 'A test template dashboard',
|
||||
downloads: 100,
|
||||
datasource: 'grafana-testdata-datasource',
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should show TemplateDashboard modal when the feature flag is enabled', async () => {
|
||||
render(<BrowseDashboardsPage queryParams={{}} />, {
|
||||
historyOptions: { initialEntries: [`/dashboards?templateDashboards=true`] },
|
||||
});
|
||||
expect(await screen.findByRole('dialog', { name: 'Start a dashboard from a template' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show TemplateDashboard modal when the feature flag is disabled', async () => {
|
||||
config.featureToggles.dashboardTemplates = false;
|
||||
render(<BrowseDashboardsPage queryParams={{}} />, {
|
||||
historyOptions: { initialEntries: [`/dashboards?templateDashboards=true`] },
|
||||
});
|
||||
expect(screen.queryByRole('dialog', { name: 'Start a dashboard from a template' })).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { render as rtlRender, screen, within } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { TestProvider } from 'test/helpers/TestProvider';
|
||||
import { screen, within } from '@testing-library/react';
|
||||
import { render } from 'test/test-utils';
|
||||
|
||||
import { config } from '@grafana/runtime';
|
||||
import { ManagerKind } from 'app/features/apiserver/types';
|
||||
import { useIsProvisionedInstance } from 'app/features/provisioning/hooks/useIsProvisionedInstance';
|
||||
import { FolderDTO } from 'app/types/folders';
|
||||
@@ -14,18 +14,29 @@ jest.mock('app/features/provisioning/hooks/useIsProvisionedInstance', () => ({
|
||||
useIsProvisionedInstance: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@grafana/runtime', () => {
|
||||
return {
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
getDataSourceSrv: () => ({
|
||||
getList: jest
|
||||
.fn()
|
||||
.mockReturnValue([
|
||||
{ name: 'Test Data Source', uid: 'test-data-source-uid', type: 'grafana-testdata-datasource' },
|
||||
]),
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
const mockUseIsProvisionedInstance = useIsProvisionedInstance as jest.MockedFunction<typeof useIsProvisionedInstance>;
|
||||
|
||||
const mockParentFolder = mockFolderDTO();
|
||||
|
||||
function render(...[ui, options]: Parameters<typeof rtlRender>) {
|
||||
rtlRender(<TestProvider>{ui}</TestProvider>, options);
|
||||
}
|
||||
|
||||
async function renderAndOpen(folder?: FolderDTO) {
|
||||
render(<CreateNewButton canCreateDashboard canCreateFolder parentFolder={folder} isReadOnlyRepo={false} />);
|
||||
const { user } = render(
|
||||
<CreateNewButton canCreateDashboard canCreateFolder parentFolder={folder} isReadOnlyRepo={false} />
|
||||
);
|
||||
const newButton = screen.getByText('New');
|
||||
await userEvent.click(newButton);
|
||||
await user.click(newButton);
|
||||
}
|
||||
|
||||
describe('NewActionsButton', () => {
|
||||
@@ -53,13 +64,13 @@ describe('NewActionsButton', () => {
|
||||
});
|
||||
|
||||
it('clicking the "New folder" button opens the drawer', async () => {
|
||||
render(
|
||||
const { user } = render(
|
||||
<CreateNewButton canCreateDashboard canCreateFolder parentFolder={mockParentFolder} isReadOnlyRepo={false} />
|
||||
);
|
||||
|
||||
const newButton = screen.getByText('New');
|
||||
await userEvent.click(newButton);
|
||||
await userEvent.click(screen.getByText('New folder'));
|
||||
await user.click(newButton);
|
||||
await user.click(screen.getByText('New folder'));
|
||||
|
||||
const drawer = screen.getByRole('dialog', { name: 'Drawer title New folder' });
|
||||
expect(drawer).toBeInTheDocument();
|
||||
@@ -68,9 +79,9 @@ describe('NewActionsButton', () => {
|
||||
});
|
||||
|
||||
it('should only render dashboard items when folder creation is disabled', async () => {
|
||||
render(<CreateNewButton canCreateDashboard canCreateFolder={false} isReadOnlyRepo={false} />);
|
||||
const { user } = render(<CreateNewButton canCreateDashboard canCreateFolder={false} isReadOnlyRepo={false} />);
|
||||
const newButton = screen.getByText('New');
|
||||
await userEvent.click(newButton);
|
||||
await user.click(newButton);
|
||||
|
||||
expect(screen.getByRole('link', { name: 'New dashboard' })).toBeInTheDocument();
|
||||
expect(screen.getByText('Import')).toBeInTheDocument();
|
||||
@@ -78,9 +89,9 @@ describe('NewActionsButton', () => {
|
||||
});
|
||||
|
||||
it('should only render folder item when dashboard creation is disabled', async () => {
|
||||
render(<CreateNewButton canCreateDashboard={false} canCreateFolder isReadOnlyRepo={false} />);
|
||||
const { user } = render(<CreateNewButton canCreateDashboard={false} canCreateFolder isReadOnlyRepo={false} />);
|
||||
const newButton = screen.getByText('New');
|
||||
await userEvent.click(newButton);
|
||||
await user.click(newButton);
|
||||
|
||||
expect(screen.queryByText('New dashboard')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('Import')).not.toBeInTheDocument();
|
||||
@@ -124,4 +135,27 @@ describe('NewActionsButton', () => {
|
||||
expect(screen.getByText('New folder')).toBeInTheDocument();
|
||||
expect(screen.queryByText('Import')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('Dashboard from template button', () => {
|
||||
beforeEach(() => {
|
||||
config.featureToggles.dashboardTemplates = true;
|
||||
});
|
||||
|
||||
it('should show a `Dashboard from template` button when the feature flag is enabled', async () => {
|
||||
await renderAndOpen();
|
||||
expect(screen.getByRole('link', { name: 'Dashboard from template' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show a `Dashboard from template` button when the feature flag is disabled', async () => {
|
||||
config.featureToggles.dashboardTemplates = false;
|
||||
await renderAndOpen();
|
||||
expect(screen.queryByRole('link', { name: 'Dashboard from template' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should redirect the user to the dashboard from template page when the button is clicked', async () => {
|
||||
await renderAndOpen();
|
||||
const link = screen.getByRole('link', { name: 'Dashboard from template' });
|
||||
expect(link).toHaveAttribute('href', '/dashboards?templateDashboards=true&source=createNewButton');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { render, screen, waitFor } from 'test/test-utils';
|
||||
|
||||
import { setBackendSrv } from '@grafana/runtime';
|
||||
import server, { setupMockServer } from '@grafana/test-utils/server';
|
||||
import { backendSrv } from 'app/core/services/backend_srv';
|
||||
|
||||
import { TemplateDashboardModal } from './TemplateDashboardModal';
|
||||
|
||||
setBackendSrv(backendSrv);
|
||||
setupMockServer();
|
||||
|
||||
const mockGetList = jest
|
||||
.fn()
|
||||
.mockReturnValue([{ name: 'Test Data Source', uid: 'test-data-source-uid', type: 'grafana-testdata-datasource' }]);
|
||||
|
||||
jest.mock('@grafana/runtime', () => {
|
||||
return {
|
||||
...jest.requireActual('@grafana/runtime'),
|
||||
getDataSourceSrv: () => ({
|
||||
getList: mockGetList,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
describe('TemplateDashboardModal', () => {
|
||||
beforeEach(() => {
|
||||
mockGetList.mockReturnValue([
|
||||
{ name: 'Test Data Source', uid: 'test-data-source-uid', type: 'grafana-testdata-datasource' },
|
||||
]);
|
||||
server.use(
|
||||
http.get('/api/gnet/dashboards', () => {
|
||||
return HttpResponse.json({
|
||||
page: 1,
|
||||
pages: 1,
|
||||
items: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Test Template Dashboard',
|
||||
description: 'A test template dashboard',
|
||||
downloads: 100,
|
||||
datasource: 'grafana-testdata-datasource',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Test Template Dashboard 2',
|
||||
description: 'A test template dashboard 2',
|
||||
downloads: 100,
|
||||
datasource: 'grafana-testdata-datasource',
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
describe('Render conditions', () => {
|
||||
it('should show TemplateDashboard modal when query param is present, test data source is available and there are template dashboards', async () => {
|
||||
render(<TemplateDashboardModal />, {
|
||||
historyOptions: { initialEntries: [`/dashboards?templateDashboards=true`] },
|
||||
});
|
||||
expect(await screen.findByRole('dialog', { name: 'Start a dashboard from a template' })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show TemplateDashboard modal when query param is present but test data source is not available', async () => {
|
||||
mockGetList.mockReturnValueOnce([]);
|
||||
render(<TemplateDashboardModal />, {
|
||||
historyOptions: { initialEntries: [`/dashboards?templateDashboards=true`] },
|
||||
});
|
||||
expect(screen.queryByRole('dialog', { name: 'Start a dashboard from a template' })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should not show TemplateDashboard modal when query param is present but there are no template dashboards', async () => {
|
||||
server.use(
|
||||
http.get('/api/gnet/dashboards', () => {
|
||||
return HttpResponse.json({
|
||||
page: 1,
|
||||
pages: 1,
|
||||
items: [],
|
||||
});
|
||||
})
|
||||
);
|
||||
render(<TemplateDashboardModal />, {
|
||||
historyOptions: { initialEntries: [`/dashboards?templateDashboards=true`] },
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole('dialog', { name: 'Start a dashboard from a template' })).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not show TemplateDashboard modal when query param is not present', async () => {
|
||||
render(<TemplateDashboardModal />);
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole('dialog', { name: 'Start a dashboard from a template' })).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Render content', () => {
|
||||
it('should render title and description', async () => {
|
||||
render(<TemplateDashboardModal />, {
|
||||
historyOptions: { initialEntries: [`/dashboards?templateDashboards=true`] },
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Start a dashboard from a template')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(
|
||||
screen.getByText(
|
||||
'Get started with Grafana templates using sample data. Connect your data to power them with real metrics.'
|
||||
)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
it('should show template dashboard cards', async () => {
|
||||
render(<TemplateDashboardModal />, {
|
||||
historyOptions: { initialEntries: [`/dashboards?templateDashboards=true`] },
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
// Assert DashboardCard components are rendered by checking for their headings
|
||||
expect(screen.getByRole('heading', { name: 'Test Template Dashboard' })).toBeInTheDocument();
|
||||
expect(screen.getByRole('heading', { name: 'Test Template Dashboard 2' })).toBeInTheDocument();
|
||||
|
||||
// Assert DashboardCard components are rendered by checking for "Use template" buttons
|
||||
const useTemplateButtons = screen.getAllByRole('button', { name: 'Use template' });
|
||||
expect(useTemplateButtons).toHaveLength(2);
|
||||
|
||||
// Assert text content (descriptions)
|
||||
expect(screen.getByText('A test template dashboard')).toBeInTheDocument();
|
||||
expect(screen.getByText('A test template dashboard 2')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user